package org.sixtynine.stock.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;

import org.apache.log4j.Logger;
import org.sixtynine.stock.Constants;
import org.sixtynine.stock.ReturnData;
import org.sixtynine.stock.cache.CompanyCache;
import org.sixtynine.stock.cache.CompanyDto;
import org.sixtynine.stock.cache.CurrentShareCache;
import org.sixtynine.stock.cache.SectorCache;
import org.sixtynine.stock.cache.SectorDto;
import org.sixtynine.stock.criteria.StockSearchCriteria;
import org.sixtynine.stock.entity.AnnualShareData;
import org.sixtynine.stock.entity.BaseEntity;
import org.sixtynine.stock.entity.Company;
import org.sixtynine.stock.entity.DailySectorData;
import org.sixtynine.stock.entity.DailyShareData;
import org.sixtynine.stock.entity.Dividend;
import org.sixtynine.stock.entity.IntradaySectorData;
import org.sixtynine.stock.entity.IntradayShareData;
import org.sixtynine.stock.entity.QuarterlyShareData;
import org.sixtynine.stock.entity.User;
import org.sixtynine.stock.result.DividendResult;
import org.sixtynine.stock.result.ShareResult;
import org.sixtynine.stock.result.StockResult;
import org.sixtynine.stock.service.business.StockCalculator;
import org.sixtynine.stock.service.business.StockUtil;
import org.sixtynine.stock.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

/**
 * this is the main business layer interface
 * 
 * @author Thilanka
 * @param <E>
 * 
 */
@Service
public class StockManagerServiceImpl<E> implements StockManagerService {

	@Autowired
	StockPersistentService service;

	@Autowired
	CurrentShareCache currentShareCache;

	@Autowired
	DividendService dividendService;

	@Override
	public User login(String userName, String passwords) {
		User userData = null;
		userData = service.findUserByUserName(userName);
		return userData;
	}

	@Autowired
	private CompanyCache companyCache;
	@Autowired
	private SectorCache sectorCache;

	private static Logger logger = Logger
			.getLogger(StockManagerServiceImpl.class);

	/**
	 * @param criteria
	 * @param companyDto
	 * @return whether the company match the filter logic
	 */
	private boolean validForFilterConditions(StockSearchCriteria criteria,
			CompanyDto companyDto) {

		Company company = companyDto.getCompany();

		// continue if company is invalid
		if (!company.isStatus()) {
			return false;
		}

		if (criteria.getIndex() != null && !criteria.getIndex().equals("-1")) {
			if (criteria.getIndex().equals(StockSearchCriteria.INDEX_ASI)) {
				if (!company.getAsi()) {
					return false;
				}
			}

			if (criteria.getIndex().equals(StockSearchCriteria.INDEX_SNP)) {
				if (!company.getSnp()) {
					return false;
				}
			}
		}

		if (StockUtil.isDropdownValueSelected(criteria.getSectorCode())) {

			// either sector code or sub sector code should match
			if (!(company.getSector().getCode()
					.equals(criteria.getSectorCode()) || StockUtil
					.isSubSectorMatched(criteria.getSectorCode(), company))) {
				return false;
			}
		}

		// company name and code filters
		if (!StringUtils.isEmpty(criteria.getCompanyName())
				&& !StockUtil
						.like(company.getName(), criteria.getCompanyName())) {
			return false;
		}

		if (!StringUtils.isEmpty(criteria.getTicker())
				&& !StockUtil.like(company.getCode(), criteria.getTicker())) {
			return false;
		}

		return true;
	}

	/**
	 * populate the basic details of the share result
	 * 
	 * @param company
	 * @param shareResult
	 */
	private static void setCompanyData(final Company company,
			ShareResult shareResult) {

		if (company.getSector() != null) {
			shareResult.setSector(company.getSector().getCode());
		}
		shareResult.setTicker(company.getCode());
		shareResult.setCompanyName(company.getName());
		if (company.getAsi()) {
			shareResult.setIndex(Constants.SECTOR_ASI);
		} else if (company.getSnp()) {
			shareResult.setIndex(Constants.SECTOR_SNP_CODE);
		}

	}

	/**
	 * calculate and set the sma values
	 * 
	 * @param shareResult
	 * @param companyDto
	 * @param currentShare
	 * @param criteria
	 * @return
	 */
	private static boolean setSmaValues(ShareResult shareResult,
			CompanyDto companyDto, IntradayShareData currentShare,
			StockSearchCriteria criteria) {

		shareResult.setSma10(StockCalculator.getBean().calculateSmaVal(
				companyDto.getDailyShareData(), Constants.SMA_TEN_DAYS,
				currentShare));

		/*
		 * shareResult.setSma10(StockCalculator.getBean().calculateSmaVal(
		 * companyDto._getClosingPrices(), 10,
		 * currentShare.getLastTradedPrice()));
		 */

		if (!StockUtil.filterValues(criteria.getSmaTen(),
				shareResult.getSma10())) {
			return false;
		}

		shareResult.setSma20(StockCalculator.getBean().calculateSmaVal(
				companyDto.getDailyShareData(), Constants.SMA_TWENTY_DAYS,
				currentShare));
		if (!StockUtil.filterValues(criteria.getSmaTwenty(),
				shareResult.getSma20())) {
			return false;
		}

		shareResult.setSma50(StockCalculator.getBean().calculateSmaVal(
				companyDto.getDailyShareData(), Constants.SMA_FIFTY_DAYS,
				currentShare));

		if (!StockUtil.filterValues(criteria.getSmaFifty(),
				shareResult.getSma50())) {
			return false;
		}

		shareResult.setSma100(StockCalculator.getBean().calculateSmaVal(
				companyDto.getDailyShareData(), Constants.SMA_HUNDRED_DAYS,
				currentShare));

		if (!StockUtil.filterValues(criteria.getSmaHundred(),
				shareResult.getSma100())) {
			return false;
		}

		shareResult.setSma200(StockCalculator.getBean().calculateSmaVal(
				companyDto.getDailyShareData(), Constants.SMA_TWO_HUNDRED_DAYS,
				currentShare));

		if (!StockUtil.filterValues(criteria.getSmaTwoHundred(),
				shareResult.getSma200())) {
			return false;
		}

		return true;

	}

	/**
	 * @param shareResult
	 * @param companyDto
	 * @param currentShare
	 * @param criteria
	 * @return whether it match the search criteria
	 */
	private static boolean setDailyDataRelatedValues(ShareResult shareResult,
			CompanyDto companyDto, IntradayShareData currentShare,
			StockSearchCriteria criteria, DailyShareData lastDayShare) {

		boolean valid = setSmaValues(shareResult, companyDto, currentShare,
				criteria);
		if (!valid) {
			return false;
		}
		shareResult.setNoOfShares((int) lastDayShare.getNoOfTrade());

		/*
		 * shareResult.setRsi(StockCalculator.getBean().calculateRsi(
		 * companyDto._getClosingPriceWithCurrentShare(currentShare)));
		 */

		shareResult.setRsi(StockCalculator.getBean().calculateRsi(
				companyDto._getClosingPrices()));

		if (!StockUtil.filterValues(criteria.getRsi(), shareResult.getRsi())) {
			return false;
		}

		return true;
	}

	/**
	 * @param shareResult
	 * @param lastQuarterlyShareData
	 * @param lastSecondQuarterlyShareData
	 * @param criteria
	 * @param currentShare
	 * @param companyDto
	 * @param lastDayShare
	 * @return
	 */
	private static boolean setQuarterDataRelatedValues(ShareResult shareResult,
			QuarterlyShareData lastQuarterlyShareData,
			QuarterlyShareData lastSecondQuarterlyShareData,
			StockSearchCriteria criteria, IntradayShareData currentShare,
			CompanyDto companyDto, DailyShareData lastDayShare) {

		/** database value start */
		shareResult.setNoOfShareIssued((int) lastQuarterlyShareData
				.getTotShareOutstand());
		/** database value end */

		shareResult.setInsiderTransaction(StockCalculator.getBean()
				.getInsiderTransactions(
						lastSecondQuarterlyShareData.getPercentOwnbyInsiders(),
						lastQuarterlyShareData.getPercentOwnbyInsiders()));
		if (!StockUtil.filterValues(criteria.getInsiderOwnership(),
				shareResult.getChangeInsiderOwnership())) {
			return false;
		}

		shareResult.setInstitutionalTransaction(StockCalculator.getBean()
				.getInsiderTransactions(
						lastSecondQuarterlyShareData.getInstOwnership(),
						lastQuarterlyShareData.getInstOwnership()));
		if (!StockUtil.filterValues(criteria.getInstitutionalOwnership(),
				shareResult.getChangeInstitutionalOwnership())) {
			return false;
		}

		shareResult.setFreeFloatMn(lastQuarterlyShareData
				.getSharesInFreefloat() * currentShare.getLastTradedPrice());
		shareResult.setEps(lastQuarterlyShareData.getRecurringNetProfit()
				/ lastQuarterlyShareData.getWeightedAverage());

		shareResult.setMarketCap(lastQuarterlyShareData
				.getAdjestedTotalAssets() * currentShare.getLastTradedPrice());
		if (!StockUtil.filterValues(criteria.getMktCap(),
				shareResult.getMarketCap())) {
			return false;
		}

		if (lastQuarterlyShareData.getTotShareOutstand() != 0) {
			shareResult.setBvps(lastQuarterlyShareData
					.getAdjestedEquityShareholder()
					/ lastQuarterlyShareData.getTotShareOutstand());
		}

		if (shareResult.getBvps() != 0) {
			shareResult.setPbv(currentShare.getLastTradedPrice()
					/ (shareResult.getBvps()));
		}
		if (!StockUtil.filterValues(criteria.getPbv(), shareResult.getPbv())) {
			return false;
		}

		shareResult.setFourQtrEps(StockCalculator.getBean()
				.calculateFourQuarterEpsGrowth(
						companyDto.getQuarterlyShareData(),
						lastQuarterlyShareData));

		// set four quarter eps growth filter
		if (!StockUtil.filterValues(criteria.getLstFourQtrEps(),
				shareResult.getQtrQoqEps())) {
			return false;
		}

		shareResult
				.setDebitToequity((lastQuarterlyShareData.getDebt() / lastQuarterlyShareData
						.getAverageEquity()) * 100);
		if (!StockUtil.filterValues(criteria.getDebtToEquity(),
				shareResult.getDebitToequity())) {
			return false;
		}

		shareResult.setEbitda(lastQuarterlyShareData.getEbitda());
		if (!StockUtil.filterValues(criteria.getEbitda(),
				shareResult.getEbitda())) {
			return false;
		}

		shareResult.setEquity(lastQuarterlyShareData.getEquityToSharehol());

		shareResult.setFreeFloatShareprice(lastQuarterlyShareData
				.getSharesInFreefloat() * lastDayShare.getSharePrice());
		if (!StockUtil.filterValues(criteria.getFreeFloatLkr(),
				shareResult.getFreeFloatShareprice())) {
			return false;
		}

		shareResult.setFreeFloatShares(lastQuarterlyShareData
				.getSharesInFreefloat());

		shareResult
				.setGearing((lastQuarterlyShareData.getDebt() / lastQuarterlyShareData
						.getAverageTotalAsse()) * 100);
		if (!StockUtil.filterValues(criteria.getGearing(),
				shareResult.getGearing())) {
			return false;
		}

		shareResult.setInsiderOwnership(lastQuarterlyShareData
				.getPercentOwnbyInsiders());
		if (!StockUtil.filterValues(criteria.getInsiderOwnership(),
				shareResult.getInsiderOwnership())) {
			return false;
		}

		shareResult.setInstitutionalOwnership(lastQuarterlyShareData
				.getInstOwnership());
		if (!StockUtil.filterValues(criteria.getInstitutionalOwnership(),
				shareResult.getInstitutionalOwnership())) {
			return false;
		}

		shareResult
				.setNetProfit(lastQuarterlyShareData.getRecurringNetProfit());
		shareResult.setNoOfShareFreeFloat(lastQuarterlyShareData
				.getSharesInFreefloat());

		shareResult.setPer(currentShare.getLastTradedPrice()
				/ StockCalculator.getBean().calculateFourQuarterEps(
						companyDto.getQuarterlyShareData(),
						lastQuarterlyShareData.getLstFourQtrWeighted()));
		if (!StockUtil.filterValues(criteria.getPer(), shareResult.getPer())) {
			return false;
		}

		shareResult.setRoa(StockCalculator.getBean().calculateRoa(
				lastQuarterlyShareData, companyDto.getQuarterlyShareData()));
		if (!StockUtil.filterValues(criteria.getRoa(), shareResult.getRoa())) {
			return false;
		}

		shareResult
				.setRoe((lastQuarterlyShareData.getLstFourQtrRecurringProfit() / StockCalculator
						.getBean().calculateAvarageEquity(
								companyDto.getQuarterlyShareData())) * 100);
		if (!StockUtil.filterValues(criteria.getRoe(), shareResult.getRoe())) {
			return false;
		}

		shareResult.setTotalAssets(lastQuarterlyShareData.getAverageEquity());
		shareResult.setTotaldebt(lastQuarterlyShareData.getDebt());
		shareResult.setCurrenRatio(lastQuarterlyShareData.getCurrentAssets()
				/ lastQuarterlyShareData.getCurrentLiability());
		shareResult.setCashPerShare(lastQuarterlyShareData.getCash()
				/ lastQuarterlyShareData.getTotShareOutstand());

		shareResult.setTotalShareOutStanding(lastQuarterlyShareData
				.getTotShareOutstand());
		shareResult.setRecuringProfit(lastQuarterlyShareData
				.getRecurringNetProfit());
		shareResult.setWaitedAvarageShare(lastQuarterlyShareData
				.getWeightedAverage());
		shareResult.setEquityToShareHolder(lastQuarterlyShareData
				.getEquityToSharehol());
		shareResult.setTotalShareOutStanding(lastQuarterlyShareData
				.getTotShareOutstand());

		return true;
	}

	/**
	 * @param shareResult
	 * @param lastAnnualShareData
	 * @param criteria
	 * @param currentShare
	 * @return
	 */
	private static boolean setYearlyDataRelatedValues(ShareResult shareResult,
			AnnualShareData lastAnnualShareData, StockSearchCriteria criteria,
			IntradayShareData currentShare) {
		shareResult.setDps(lastAnnualShareData.getDividenOfShare()
				/ lastAnnualShareData.getNumberOfShares());

		shareResult
				.setDy(((lastAnnualShareData.getDividenOfShare() / lastAnnualShareData
						.getAveShareOfShare()) / currentShare
						.getLastTradedPrice()) * 100);

		/*
		 * shareResult .setDy((lastAnnualShareData.getDividenOfShare() /
		 * lastAnnualShareData .getAveShareOfShare()) * 100);
		 */if (!StockUtil.filterValues(criteria.getDy(), shareResult.getDy())) {
			return false;
		}

		shareResult.setDevidend(lastAnnualShareData.getDividents());
		shareResult
				.setDevidentPayOut((lastAnnualShareData.getDividents() / lastAnnualShareData
						.getNetProfit()) * 100);
		if (!StockUtil.filterValues(criteria.getDividendPayout(),
				shareResult.getDevidentPayOut())) {
			return false;
		}

		shareResult.setLastAnnumEps(lastAnnualShareData.getNetProfit()
				/ lastAnnualShareData.getNumberOfShares());
		shareResult.setLastFinancealYearRevenues(lastAnnualShareData
				.getRevenues());

		shareResult.setPerLastFy(currentShare.getLastTradedPrice()
				/ StockCalculator.getBean().calculateEps(
						lastAnnualShareData.getRecurringProfit(),
						lastAnnualShareData.getNumberOfShares()));

		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.sixtynine.stock.service.StockManagerService#search(org.sixtynine.
	 * stock.criteria.StockSearchCriteria)
	 */
	@Override
	public ReturnData<List<ShareResult>> search(StockSearchCriteria criteria) {

		ReturnData<List<ShareResult>> returnData = new ReturnData<List<ShareResult>>();

		try {
			List<CompanyDto> companies = companyCache
					.get(Constants.COMPANY_CACHED_DATA);

			SectorDto asiSector = sectorCache.get(Constants.SECTOR_CACHED_DATA,
					Constants.SECTOR_ASI);

			List<ShareResult> shareResults = new ArrayList<ShareResult>();

			double totalMarketCap = 0.00;
			double totalShareOutstanding = 0.00;
			double totalRecurringProfit = 0;
			double totalWaitedAvarageShare = 0;
			double totalEquitytoShareHol = 0;
			double totaldividens = 0;
			double totalLstDayMktCap = 0;

			boolean isCurrentData = false;

			for (CompanyDto companyDto : companies) {

				// filtering
				if (!validForFilterConditions(criteria, companyDto)) {
					continue;
				}

				ShareResult shareResult = new ShareResult();

				// company related to share result
				Company company = companyDto.getCompany();
				String companyCode = company.getCode();

				// set the basic details
				setCompanyData(company, shareResult);

				// last day's share result
				if (companyDto.getDailyShareData().isEmpty()) {
					logger.error("Daily share data not avalilable for company - "
							+ companyCode);

					continue;
				}

				StockUtil.setCompanyDoc(companyDto, shareResult);

				// current share of the day
				IntradayShareData currentShare = currentShareCache
						.getCurrentShare(companyCode);

				IntradayShareData operningSharePrice = currentShareCache
						.getOpeningShare(companyCode);
				/*
				 * if (currentShare == null) {
				 * logger.error("Current Share Not Avalilale for Company - " +
				 * companyCode); continue; }
				 */

				DailyShareData lastDayShare = (DailyShareData) companyDto
						.getDailyShareData().get(0);

				// DailyShareData lastDayShare = null;

				// today's record is added, we take the yday's record as the
				// last day share
				if (currentShare != null && currentShare.getTradeVolume() != 0
						&& operningSharePrice != null) {
					for (BaseEntity baseEntity : companyDto.getDailyShareData()) {
						if (((DailyShareData) baseEntity).getVolume() > 0) {
							lastDayShare = (DailyShareData) baseEntity;
						}
					}
					if (DateUtil.isSameDay(lastDayShare.getDate(),
							currentShare.getTime())
							&& companyDto.getDailyShareData().size() > 1) {
						lastDayShare = (DailyShareData) companyDto
								.getDailyShareData().get(1);

						logger.error("is same date - " + companyCode);

						// when the data is added, we have to take the added
						// data as
						// todays current share
						DailyShareData currentDailyShareData = (DailyShareData) companyDto
								.getDailyShareData().get(0);

						// TODO set if there are any other
						currentShare.setLastTradedPrice(currentDailyShareData
								.getSharePrice());
						currentShare.setHigh(currentDailyShareData.getHigh());
						currentShare.setLow(currentDailyShareData.getLow());
						currentShare.setTradeVolume(currentDailyShareData
								.getNoOfTrade());
						currentShare.setShareVolume(currentDailyShareData
								.getVolume());
						currentShare.setTurnover(currentDailyShareData
								.getTurnOver());
						currentShare.setTime(currentDailyShareData.getDate());

						operningSharePrice = currentShare;
						isCurrentData = true;

					}
				} else {
					if (companyDto.getCompany().getDailyShareData() == null) {
						continue;
					}
					DailyShareData currentDailyShareData = (DailyShareData) companyDto
							.getDailyShareData().get(0);
					if (currentDailyShareData == null) {
						continue;
					}
					// TODO
					// newly added have to check..
					/*
					 * if (DateUtil.isSameDay(currentDailyShareData.getDate(),
					 * lastDayShare.getDate()) &&
					 * companyDto.getDailyShareData().size() > 1) { lastDayShare
					 * = (DailyShareData) companyDto
					 * .getDailyShareData().get(1); }
					 */

					currentShare = new IntradayShareData();

					operningSharePrice = new IntradayShareData();

					currentShare.setCompany(company);
					operningSharePrice.setCompany(company);

					// TODO set if there are any other
					currentShare.setLastTradedPrice(currentDailyShareData
							.getSharePrice());
					currentShare.setHigh(currentDailyShareData.getHigh());
					currentShare.setLow(currentDailyShareData.getLow());
					currentShare.setTradeVolume(currentDailyShareData
							.getNoOfTrade());
					currentShare.setShareVolume(currentDailyShareData
							.getVolume());
					currentShare.setTurnover(currentDailyShareData
							.getTurnOver());

					currentShare.setTime(currentDailyShareData.getDate());

					operningSharePrice = currentShare;

				}

				/*
				 * if (operningSharePrice.getTradeVolume() == 0) {
				 * operningSharePrice.setLastTradedPrice(0.00); }
				 */

				if (isCurrentData) {
					if (operningSharePrice.getLastTradedPrice() > 0) {
						shareResult.setGap((operningSharePrice
								.getLastTradedPrice()
								/ lastDayShare.getSharePrice() - 1) * 100);
					} else {
						shareResult.setGap(0);
					}

				} else {
					if (companyDto.getDailyShareData().size() > 1
							&& companyDto.getCompany().getDailyShareData() != null) {
						DailyShareData lastTradingDate = (DailyShareData) companyDto
								.getDailyShareData().get(1);
						if (lastDayShare.getOpeningPrice() > 0) {
							shareResult
									.setGap((lastDayShare.getOpeningPrice()
											/ lastTradingDate.getSharePrice() - 1) * 100);
						} else {
							shareResult.setGap(0);
						}
					}

				}

				if (!StockUtil.filterValues(criteria.getGap(),
						shareResult.getGap())) {
					continue;
				}

				// if share price is zero, that means there are no trades for
				// the day. In that case we need to get the yesterdays closing
				// price
				if (currentShare.getLastTradedPrice() == 0) {
					currentShare.setLastTradedPrice(lastDayShare
							.getSharePrice());
				}
				shareResult.setCurrentSharePrice(currentShare
						.getLastTradedPrice());

				// filter share price
				if (!StockUtil.filterValues(criteria.getSharePrice(),
						shareResult.getCurrentSharePrice())) {
					continue;
				}

				shareResult.setVolume(currentShare.getShareVolume());
				// filter current volume
				if (!StockUtil.filterValues(criteria.getCurrentVolume(),
						shareResult.getVolume())) {
					continue;
				}
				// yesterdays closing price as the share price
				shareResult.setSharePrice(lastDayShare.getSharePrice());
				// TODO

				boolean valid = setDailyDataRelatedValues(shareResult,
						companyDto, currentShare, criteria, lastDayShare);
				if (!valid) {
					continue;
				}

				// TODO - check calculation with api
				if (CurrentShareCache.isBeforeMarketOpen()) {
					shareResult.setChange(0);
				} else {
					if (!DateUtil.isSameDay(currentShare.getTime(),
							lastDayShare.getDate())) {
						shareResult.setChange(((currentShare
								.getLastTradedPrice() / lastDayShare
								.getSharePrice()) - 1) * 100);
					} else if (companyDto.getDailyShareData().size() > 1) {
						DailyShareData lastTradeDayShare = (DailyShareData) companyDto
								.getDailyShareData().get(1);
						shareResult.setChange(((currentShare
								.getLastTradedPrice() / lastTradeDayShare
								.getSharePrice()) - 1) * 100);
					}

				}

				if (!StockUtil.filterValues(criteria.getChange(),
						shareResult.getChange())) {
					continue;
				}

				// we can set quarterly data if at least 2 records.
				if (companyDto.getQuarterlyShareData().size() > 1) {
					QuarterlyShareData lastQuarterlyShareData = (QuarterlyShareData) companyDto
							.getQuarterlyShareData().get(0);
					QuarterlyShareData lastSecondQuarterlyShareData = (QuarterlyShareData) companyDto
							.getQuarterlyShareData().get(1);
					valid = setQuarterDataRelatedValues(shareResult,
							lastQuarterlyShareData,
							lastSecondQuarterlyShareData, criteria,
							currentShare, companyDto, lastDayShare);
					if (!valid) {
						continue;
					}
				}

				// here we need both quarterly and annual data
				if (companyDto.getQuarterlyShareData().size() > 0
						&& companyDto.getAnnualShareData().size() > 0) {
					QuarterlyShareData lastQuarterlyShareData = (QuarterlyShareData) companyDto
							.getQuarterlyShareData().get(0);
					AnnualShareData lastAnnualShareData = (AnnualShareData) companyDto
							.getAnnualShareData().get(0);

					shareResult.setCashPerShare(lastQuarterlyShareData
							.getCash()
							/ lastQuarterlyShareData.getTotShareOutstand());
				}

				if (!companyDto.getAnnualShareData().isEmpty()) {
					AnnualShareData lastAnnualShareData = (AnnualShareData) companyDto
							.getAnnualShareData().get(0);
					valid = setYearlyDataRelatedValues(shareResult,
							lastAnnualShareData, criteria, currentShare);
					if (!valid) {
						continue;
					}
				}

				shareResult.setAvarageVolume(StockCalculator.getBean()
						.calculateAvarageVolume(companyDto.getDailyShareData(),
								Constants.AVG_DAYS_PER_MONTH * 3));
				if (!StockUtil.filterValues(criteria.getAveVolume(),
						shareResult.getAvarageVolume())) {
					continue;
				}

				shareResult.setRelativeVolume(currentShare.getShareVolume()
						/ shareResult.getAvarageVolume());
				if (!StockUtil.filterValues(criteria.getRelativeVolume(),
						shareResult.getRelativeVolume())) {
					continue;
				}

				if (!StockUtil.filterValues(criteria.getPerLastFy(),
						shareResult.getPerLastFy())) {
					continue;
				}

				double twelveMonthLow = (StockCalculator.getBean()
						.getMonthlyLow(companyDto._getAllLow(),
								Constants.PRICE_PERF_DAYS_PER_YEAR));

				shareResult.setTwelMonthLow((currentShare.getLastTradedPrice()
						/ twelveMonthLow - 1) * 100);
				if (!StockUtil.filterValues(criteria.getTwelveMonthHighLow(),
						shareResult.getTwelMonthLow())) {
					continue;
				}

				double twelveMonthHigh = (StockCalculator.getBean()
						.getMonthlyHigh(companyDto._getAllHigh(),
								Constants.PRICE_PERF_DAYS_PER_YEAR));

				shareResult.setTwelMonthHigh((currentShare.getLastTradedPrice()
						/ twelveMonthHigh - 1) * 100);
				if (!StockUtil.filterValues(criteria.getTwelveMonthHighLow(),
						shareResult.getTwelMonthHigh())) {
					continue;
				}

				double threeMHigh = (StockCalculator.getBean()
						.getHighWithCurrent(currentShare,
								companyDto.getDailyShareData(),
								Constants.PRICE_PERF_DAYS_THREE_MONTH));
				shareResult.setThreeMHigh((currentShare.getLastTradedPrice()
						/ threeMHigh - 1) * 100);
				if (!StockUtil.filterValues(criteria.getThreeMHigh(),
						shareResult.getThreeMHigh())) {
					continue;
				}

				// 3M low
				double threeMLow = (StockCalculator.getBean()
						.getLowWithCurrent(currentShare,
								companyDto.getDailyShareData(),
								Constants.PRICE_PERF_DAYS_THREE_MONTH));

				shareResult.setThreeMLow((currentShare.getLastTradedPrice()
						/ threeMLow - 1) * 100);
				if (!StockUtil.filterValues(criteria.getThreeMLow(),
						shareResult.getThreeMLow())) {
					continue;
				}

				// 6M high
				double sixMHigh = (StockCalculator.getBean()
						.getHighWithCurrent(currentShare,
								companyDto.getDailyShareData(),
								Constants.PRICE_PERF_DAYS_SIX_MONTH));

				shareResult.setSixMHigh((currentShare.getLastTradedPrice()
						/ sixMHigh - 1) * 100);
				if (!StockUtil.filterValues(criteria.getSixMHigh(),
						shareResult.getSixMHigh())) {
					continue;
				}

				// 6M low
				double sixMLow = (StockCalculator.getBean().getLowWithCurrent(
						currentShare, companyDto.getDailyShareData(),
						Constants.PRICE_PERF_DAYS_SIX_MONTH));

				shareResult.setSixMLow((currentShare.getLastTradedPrice()
						/ sixMLow - 1) * 100);
				if (!StockUtil.filterValues(criteria.getSixMLow(),
						shareResult.getSixMLow())) {
					continue;
				}

				// one month high and low

				double oneMLow = (StockCalculator.getBean().getLowWithCurrent(
						currentShare, companyDto.getDailyShareData(),
						Constants.PRICE_PERF_DAYS_PER_MONTH));
				shareResult.setOneMLow((currentShare.getLastTradedPrice()
						/ oneMLow - 1) * 100);
				if (!StockUtil.filterValues(criteria.getOneMLow(),
						shareResult.getOneMLow())) {
					continue;
				}

				double oneMHigh = (StockCalculator.getBean()
						.getHighWithCurrent(currentShare,
								companyDto.getDailyShareData(),
								Constants.PRICE_PERF_DAYS_PER_MONTH));
				shareResult.setOneMHigh((currentShare.getLastTradedPrice()
						/ oneMHigh - 1) * 100);
				if (!StockUtil.filterValues(criteria.getOneMHigh(),
						shareResult.getOneMHigh())) {
					continue;
				}

				// beta calculation
				shareResult.setSixtyMonthBeta(StockCalculator.getBean()
						.calculateBeta(
								asiSector._getAspiMonthlyClosingPrices(),
								companyDto._getMonthlyClosingPrices(),
								Constants.AVG_MONTH_PER_YEAR * 5));
				if (!StockUtil.filterValues(criteria.getBeta(),
						shareResult.getSixtyMonthBeta())) {
					continue;
				}

				// beta calculation
				shareResult.setThertyMonthBeta(StockCalculator.getBean()
						.calculateBeta(
								asiSector._getAspiMonthlyClosingPrices(),
								companyDto._getMonthlyClosingPrices(),
								Constants.AVG_MONTH_PER_YEAR * 3));
				if (!StockUtil.filterValues(criteria.getBeta(),
						shareResult.getThertyMonthBeta())) {
					continue;
				}

				/** calculate price performance start */
				shareResult.setOneWeekPricePer(StockCalculator.getBean()
						.calculatePricePerformance(
								currentShare.getLastTradedPrice(),
								companyDto._getAllClose(),
								Constants.PRICE_PERF_DAYS_PER_WEEK));
				if (!StockUtil.filterValues(
						criteria.getFirstPricePerformence(),
						shareResult.getOneWeekPricePer())) {
					continue;
				}

				if (!StockUtil.filterValues(
						criteria.getSecondPricePerformence(),
						shareResult.getOneWeekPricePer())) {
					continue;
				}

				shareResult.setOneMonthPricePer(StockCalculator.getBean()
						.calculatePricePerformance(
								currentShare.getLastTradedPrice(),
								companyDto._getAllClose(),
								Constants.PRICE_PERF_DAYS_PER_MONTH));
				if (!StockUtil.filterValues(
						criteria.getFirstPricePerformence(),
						shareResult.getOneMonthPricePer())) {
					continue;
				}
				if (!StockUtil.filterValues(
						criteria.getSecondPricePerformence(),
						shareResult.getOneMonthPricePer())) {
					continue;
				}

				shareResult.setThreeMonthPricePer(StockCalculator.getBean()
						.calculatePricePerformance(
								currentShare.getLastTradedPrice(),
								companyDto._getAllClose(),
								Constants.PRICE_PERF_DAYS_THREE_MONTH));
				if (!StockUtil.filterValues(
						criteria.getFirstPricePerformence(),
						shareResult.getThreeMonthPricePer())) {
					continue;
				}
				if (!StockUtil.filterValues(
						criteria.getSecondPricePerformence(),
						shareResult.getThreeMonthPricePer())) {
					continue;
				}

				shareResult.setSixMonthPricePer(StockCalculator.getBean()
						.calculatePricePerformance(
								currentShare.getLastTradedPrice(),
								companyDto._getAllClose(),
								Constants.PRICE_PERF_DAYS_SIX_MONTH));
				if (!StockUtil.filterValues(
						criteria.getFirstPricePerformence(),
						shareResult.getSixMonthPricePer())) {
					continue;
				}
				if (!StockUtil.filterValues(
						criteria.getSecondPricePerformence(),
						shareResult.getSixMonthPricePer())) {
					continue;
				}

				shareResult.setTwelMonthPricePer(StockCalculator.getBean()
						.calculatePricePerformance(
								currentShare.getLastTradedPrice(),
								companyDto._getAllClose(),
								Constants.PRICE_PERF_DAYS_PER_YEAR));
				if (!StockUtil.filterValues(
						criteria.getFirstPricePerformence(),
						shareResult.getTwelMonthPricePer())) {
					continue;
				}
				if (!StockUtil.filterValues(
						criteria.getSecondPricePerformence(),
						shareResult.getTwelMonthPricePer())) {
					continue;
				}

				shareResult.setYtdPricePer(StockCalculator.getBean()
						.calculateYdt(companyDto.getDailyShareData(),
								currentShare.getLastTradedPrice()));

				shareResult.setPricePer24M(StockCalculator.getBean()
						.calculatePricePerformance(
								currentShare.getLastTradedPrice(),
								companyDto._getAllClose(),
								(Constants.PRICE_PERF_DAYS_PER_YEAR * 2)));

				/** calculate price performance end */

				/*
				 * shareResult.setOneWeekVolatility(StockCalculator.getBean()
				 * .calculateVolatility(companyDto.getDailyShareData(),
				 * Constants.PRICE_PERF_DAYS_PER_WEEK));
				 */

				shareResult.setOneWeekVolatility(StockCalculator.getBean()
						.calculateVolatility(companyDto._getAllHigh(),
								companyDto._getAllLow(),
								Constants.VOLATILITY_ONE_WEEK));

				if (!StockUtil.filterValues(criteria.getVolatility(),
						shareResult.getOneWeekVolatility())) {
					continue;
				}

				/*
				 * shareResult.setOneMonthVolatility(StockCalculator.getBean()
				 * .calculateVolatility(companyDto.getDailyShareData(),
				 * Constants.PRICE_PERF_DAYS_PER_MONTH));
				 */

				shareResult.setOneMonthVolatility(StockCalculator.getBean()
						.calculateVolatility(companyDto._getAllHigh(),
								companyDto._getAllLow(),
								Constants.VOLATILITY_ONE_MONTH));

				if (!StockUtil.filterValues(criteria.getVolatility(),
						shareResult.getOneMonthVolatility())) {
					continue;
				}

				if (!DateUtil.isSameDay(currentShare.getTime(),
						lastDayShare.getDate())) {
					shareResult
							.setAverageTrueRange(StockCalculator
									.getBean()
									.calculateAveTrueRange(
											companyDto
													._getClosingPriceWithCurrentShare(currentShare),
											companyDto
													._getHighWithCurrentShare(currentShare),
											companyDto
													._getLowWithCurrentShare(currentShare)));
				} else {
					shareResult.setAverageTrueRange(StockCalculator.getBean()
							.calculateAveTrueRange(
									companyDto._getClosingPrices(),
									companyDto._getHighPrices(),
									companyDto._getLowPrices()));
				}

				if (!StockUtil.filterValues(criteria.getAvetrueRange(),
						shareResult.getAverageTrueRange())) {
					continue;
				}

				shareResult.setQtrYoyEps(StockCalculator.getBean()
						.calculateYoYEpsGrowth(
								companyDto.getQuarterlyShareData()));
				if (!StockUtil.filterValues(criteria.getQtrEpsGrowthYoy(),
						shareResult.getQtrYoyEps())) {
					continue;
				}

				shareResult.setQtrQoqEps(StockCalculator.getBean()
						.calculateQoqEpsGrowth(
								companyDto.getQuarterlyShareData()));
				if (!StockUtil.filterValues(criteria.getEpsGrowthQoq(),
						shareResult.getQtrQoqEps())) {
					continue;
				}

				shareResult
						.setOneYearEps(StockCalculator.getBean()
								.calculateYoyEpsGrowth(
										companyDto.getAnnualShareData()));
				if (!StockUtil.filterValues(criteria.getAnnamEpsGrowthYoy(),
						shareResult.getQtrQoqEps())) {
					continue;
				}

				shareResult.setFiveYearEps(StockCalculator.getBean()
						.calculateFiveYoyEpsGrowth(
								companyDto.getAnnualShareData()));
				if (!StockUtil.filterValues(criteria.getEpsGrowthFiveYear(),
						shareResult.getFiveYearEps())) {
					continue;
				}

				// this is for broad market valuation
				shareResult
						.setTwoYearEps(StockCalculator.getBean()
								.calculateYearEps(
										companyDto.getQuarterlyShareData(), 1));
				shareResult
						.setThreeYearEps(StockCalculator.getBean()
								.calculateYearEps(
										companyDto.getQuarterlyShareData(), 2));
				shareResult
						.setFourYearEps(StockCalculator.getBean()
								.calculateYearEps(
										companyDto.getQuarterlyShareData(), 3));
				shareResult.setQtrYoyRevenue(StockCalculator.getBean()
						.calculateYoYRevernueGrowth(
								companyDto.getQuarterlyShareData()));
				shareResult.setQtrQoqRevenue(StockCalculator.getBean()
						.calculateQoqRevenueGrowth(
								companyDto.getQuarterlyShareData()));
				shareResult.setFourQtrRevenue(StockCalculator.getBean()
						.calculateFourQuarterRevernue(
								companyDto.getQuarterlyShareData()));
				shareResult.setOneYearRevenue(StockCalculator.getBean()
						.calculateYoyRevernue(companyDto.getAnnualShareData()));
				shareResult.setFiveYearRevenue(StockCalculator.getBean()
						.calculateFiveYoyRevenueGrowth(
								companyDto.getAnnualShareData()));

				shareResult.setQtrYoyEbitda(StockCalculator.getBean()
						.calculateYoYEbitdaGrowth(
								companyDto.getQuarterlyShareData()));

				shareResult.setQtrQoqEbitda(StockCalculator.getBean()
						.calculateQoqEbitdaGrowth(
								companyDto.getQuarterlyShareData()));

				shareResult.setFourQtrEbitda(StockCalculator.getBean()
						.calculateFourQuarterEbitda(
								companyDto.getQuarterlyShareData()));

				shareResult.setOneYearEbitda(StockCalculator.getBean()
						.calculateYoyEbitda(companyDto.getAnnualShareData()));

				shareResult.setFiveYearEbitda(StockCalculator.getBean()
						.calculateFiveYoyEbitdaGrowth(
								companyDto.getAnnualShareData()));

				if (currentShare.getLow() != 0 && currentShare.getHigh() != 0) {
					shareResult.setOnedayVolatality((currentShare.getHigh()
							/ currentShare.getLow() - 1) * 100);
				}

				if (isCurrentData) {
					if (currentShare.getLastTradedPrice() > 0
							&& operningSharePrice.getLastTradedPrice() > 0) {
						shareResult
								.setChangeOpenToNow((currentShare
										.getLastTradedPrice()
										/ operningSharePrice
												.getLastTradedPrice() - 1) * 100);
					} else {
						shareResult.setChangeOpenToNow(0);
					}

				} else if (lastDayShare.getSharePrice() > 0
						&& lastDayShare.getOpeningPrice() > 0) {
					shareResult
							.setChangeOpenToNow((lastDayShare.getSharePrice()
									/ lastDayShare.getOpeningPrice() - 1) * 100);
				} else {
					shareResult.setChangeOpenToNow(0);
				}

				if (!StockUtil.filterValues(criteria.getChangeOpenToNow(),
						shareResult.getChangeOpenToNow())) {
					continue;
				}

				// calculate ASI row
				if (!companyDto.getQuarterlyShareData().isEmpty()) {
					QuarterlyShareData lastQuarterlyShareData = (QuarterlyShareData) companyDto
							.getQuarterlyShareData().get(0);

					totalMarketCap += shareResult.getMarketCap();
					totalShareOutstanding += lastQuarterlyShareData
							.getTotShareOutstand();
					totalRecurringProfit += lastQuarterlyShareData
							.getRecurringNetProfit();
					totalEquitytoShareHol += lastQuarterlyShareData
							.getAdjestedEquityShareholder();
					totalWaitedAvarageShare += lastQuarterlyShareData
							.getWeightedAverage();
					totalLstDayMktCap += lastQuarterlyShareData
							.getTotShareOutstand()
							* lastDayShare.getSharePrice();
				}

				if (!companyDto.getAnnualShareData().isEmpty()) {
					AnnualShareData lastAnnualShareData = (AnnualShareData) companyDto
							.getAnnualShareData().get(0);

					totaldividens += lastAnnualShareData.getDividents();
				}

				// set the last requested date share prices
				if (criteria._getLastDate() != null) {
					shareResult.setSharePrice(StockCalculator.getBean()
							.getSharePrice(company.getId(),
									criteria._getLastDate()));
				}
				shareResults.add(shareResult);

			}

			// if total ASI record is needed to be added it will be calculated
			// here and added as a share result
			if (criteria._isAddAsiDetails()) {
				ShareResult asiShareResult = new ShareResult();
				double asiSharePrice = totalMarketCap / totalShareOutstanding;
				double asiEps = (totalRecurringProfit / totalWaitedAvarageShare);
				double bookValuePshare = totalEquitytoShareHol
						/ totalShareOutstanding;
				double asiDPS = totaldividens / totalShareOutstanding;

				asiShareResult.setCompanyName(Constants.SECTOR_ASI);
				asiShareResult.setTicker(Constants.SECTOR_ASI);
				if (asiSharePrice != 0) {
					asiShareResult.setDy((asiDPS / asiSharePrice) * 100);
				}
				asiShareResult.setMarketCap(totalMarketCap);
				if (bookValuePshare != 0) {
					asiShareResult.setPbv(asiSharePrice / bookValuePshare);
				}
				if (asiEps != 0) {
					asiShareResult.setPer(asiSharePrice / asiEps);
				}
				asiShareResult.setCurrentSharePrice(asiSharePrice);
				if (totalShareOutstanding != 0) {
					asiShareResult.setLastDaySharePrice(totalLstDayMktCap
							/ totalShareOutstanding);
				}

				IntradaySectorData intradaySectorData = currentShareCache
						.getCurrentSector(Constants.SECTOR_ASI);
				SectorDto sectorDto = sectorCache.get(Constants.SECTOR_ASI,
						Constants.SECTOR_ASI);
				if (sectorDto != null && intradaySectorData != null) {
					if (sectorDto.getDailySectorData().size() > 0) {
						DailySectorData lastDaySectorData = (DailySectorData) sectorDto
								.getDailySectorData().get(0);

						asiShareResult.setCurrentSharePrice(intradaySectorData
								.getValue());
						asiShareResult.setLastDaySharePrice(lastDaySectorData
								.getClosingValue());
					}
				}

				shareResults.add(0, asiShareResult);

			}

			returnData.setData(shareResults);
			returnData.setNo(shareResults.size());

		} catch (Exception e) {
			logger.error(e.getMessage());

			returnData.setNo(Constants.ERROR);
			returnData.setMsg(e.getMessage());
		}

		return returnData;
	}

	@Override
	public ReturnData<List<ShareResult>> searchSectorCompanies(
			StockSearchCriteria criteria) {
		ReturnData<List<ShareResult>> returnData = new ReturnData<List<ShareResult>>();

		ReturnData<List<ShareResult>> stockSearchReturnData = search(criteria);

		List<ShareResult> sectorWiseShareResults = new ArrayList<ShareResult>();
		try {
			if (stockSearchReturnData._isSuccess()) {
				List<ShareResult> shareResults = stockSearchReturnData
						.getData();
				List<SectorDto> sectors;
				sectors = sectorCache.get(Constants.SECTOR_CACHED_DATA);
				for (SectorDto sectorDto : sectors) {

					ShareResult dummySectorResult = new ShareResult();
					dummySectorResult.setCompanyName(sectorDto.getSector()
							.getName());
					dummySectorResult.setTicker(sectorDto.getSector().getCode()
							+ "-(S)");

					// TODO remove unwanted variables
					double totalMarketCap = 0;
					double totalShare = 0;
					double totalLastDayShare = 0;
					double totalChange = 0;
					double totalShareOut = 0;
					double totalRecurringProfit = 0;
					double totalWaitedAvarageShare = 0;
					double sectorSharePrice = 0;
					double totalEquitytoShareHol = 0;
					double totaldividens = 0;
					int noOfCompanies = 0;
					double currentSharePrice = 0;
					double lastdaySharePrice = 0;

					List<ShareResult> tempSectorList = new ArrayList<ShareResult>();
					for (ShareResult shareResult : shareResults) {
						if (shareResult.getSector() == null) {
							continue;
						}
						if (shareResult.getSector().equals(
								sectorDto._getSectorCode())
								&& sectorDto._getSectorCode() != "ASI") {
							currentSharePrice = shareResult
									.getCurrentSharePrice();
							currentSharePrice = shareResult
									.getCurrentSharePrice();
							totalMarketCap += shareResult.getMarketCap();
							totalShare += shareResult.getCurrentSharePrice();
							totalLastDayShare += shareResult.getSharePrice();
							totalShareOut += shareResult
									.getTotalShareOutStanding();
							totalRecurringProfit += shareResult
									.getRecuringProfit();
							totalWaitedAvarageShare += shareResult
									.getWaitedAvarageShare();
							totalEquitytoShareHol += shareResult
									.getEquityToShareHolder();
							totaldividens += shareResult.getDevidend();

							tempSectorList.add(shareResult);
						}
					}

					sectorSharePrice = totalMarketCap / totalShareOut;
					double sectorEps = (totalRecurringProfit / totalWaitedAvarageShare);

					dummySectorResult.setCurrentSharePrice(sectorSharePrice);
					dummySectorResult.setPer(sectorSharePrice / sectorEps);
					dummySectorResult.setMarketCap(totalMarketCap);
					dummySectorResult.setPbv(sectorSharePrice
							/ (totalEquitytoShareHol / totalShareOut));

					sectorWiseShareResults.add(dummySectorResult);
					sectorWiseShareResults.addAll(tempSectorList);

				}
			}

			returnData.setData(sectorWiseShareResults);

		} catch (ExecutionException e) {
			returnData.setNo(Constants.ERROR);
			returnData.setMsg(e.getMessage());
		}
		return returnData;
	}

	@Override
	public ReturnData<List<StockResult>> searchSector(
			StockSearchCriteria criteria) {
		ReturnData<List<StockResult>> returnData = new ReturnData<List<StockResult>>();

		try {
			List<StockResult> stockResults = new ArrayList<StockResult>();

			StockSearchCriteria stockSearchCriteria = new StockSearchCriteria();
			stockSearchCriteria._setStockCalculations(true);
			ReturnData<List<ShareResult>> stockSearchReturnData = search(stockSearchCriteria);
			if (stockSearchReturnData._isSuccess()) {
				List<ShareResult> shareResults = stockSearchReturnData
						.getData();
				List<SectorDto> sectors = sectorCache
						.get(Constants.SECTOR_CACHED_DATA);

				for (SectorDto sectorDto : sectors) {
					StockResult stockResult = new StockResult();
					DailySectorData lastDaySectorData = null;
					IntradaySectorData currentSectorData = null;
					if (sectorDto != null) {
						if (sectorDto.getDailySectorData().size() > 1) {
							lastDaySectorData = (DailySectorData) sectorDto
									.getDailySectorData().get(0);
						} else {
							continue;
						}
						currentSectorData = currentShareCache
								.getCurrentSector(sectorDto._getSectorCode());
						if (currentSectorData == null) {
							logger.error("Current value Not Avalilale for Sector - "
									+ sectorDto._getSectorCode());
							continue;
						}
					}

					// TODO check all the fields
					double totalMarketCap = 0;
					double totalShare = 0;
					double totalLastDayShare = 0;
					double totalChange = 0;
					double totalShareOut = 0;
					double totalRecurringProfit = 0;
					double totalWaitedAvarageShare = 0;
					double sectorSharePrice = 0;
					double totalEquitytoShareHol = 0;
					double totaldividens = 0;
					int noOfCompanies = 0;

					if (shareResults.isEmpty()) {
						continue;
					}

					boolean sectorFound = false;
					for (ShareResult shareResult : shareResults) {
						if (shareResult.getSector() == null) {
							continue;
						}
						if (shareResult.getSector().equals(
								sectorDto._getSectorCode())) {
							sectorFound = true;
							// do the calculation here
							totalMarketCap += shareResult.getMarketCap();

							// TODO All the other fields
							totalShare += shareResult.getCurrentSharePrice();
							totalLastDayShare += shareResult.getSharePrice();
							totalShareOut += shareResult
									.getTotalShareOutStanding();
							totalRecurringProfit += shareResult
									.getRecuringProfit();
							totalWaitedAvarageShare += shareResult
									.getWaitedAvarageShare();
							totalEquitytoShareHol += shareResult
									.getEquityToShareHolder();
							totaldividens += shareResult.getDevidend();
							stockResult.setSector(sectorDto._getSectorCode());

							noOfCompanies += 1;
						}
					}

					// if no companies found for the sector, we need to remove
					// them
					if (!sectorFound) {
						continue;
					}
					double sectorEps = 0;
					if (totalRecurringProfit != 0
							&& totalWaitedAvarageShare != 0) {
						sectorEps = (totalRecurringProfit / totalWaitedAvarageShare);
					}

					if (totalMarketCap != 0 && totalShareOut != 0) {
						sectorSharePrice = totalMarketCap / totalShareOut;
					}
					if (sectorSharePrice != 0 && sectorEps != 0) {
						stockResult.setPer(sectorSharePrice / sectorEps);
					}

					stockResult.setMarketCap(totalMarketCap);

					if (sectorSharePrice != 0 && totalEquitytoShareHol != 0
							&& totalShareOut != 0) {
						stockResult.setPbv(sectorSharePrice
								/ (totalEquitytoShareHol / totalShareOut));
					}
					if (totaldividens != 0 && totalShareOut != 0
							&& sectorSharePrice != 0) {
						stockResult
								.setDy(((totaldividens / totalShareOut) / sectorSharePrice) * 100);
					}
					if (currentSectorData != null && lastDaySectorData != null) {
						stockResult
								.setChange((currentSectorData.getValue()
										/ lastDaySectorData.getClosingValue() - 1) * 100);
					}

					if (lastDaySectorData != null) {
						stockResult.setPrevValue(lastDaySectorData
								.getClosingValue());

						stockResult
								.setTurnover(lastDaySectorData.getTurnOver());

					}

					if (currentSectorData != null) {
						stockResult.setCurrentValue(currentSectorData
								.getValue());
						// one week price performence
						stockResult.setOneWeekIndexPerfor(StockCalculator
								.getBean().calculatePricePerformance(
										currentSectorData.getValue(),
										sectorDto._getClosingPrices(),
										Constants.PRICE_PERF_DAYS_PER_WEEK));

						// one month price perforemence
						stockResult.setOneMonthIndexPerfor(StockCalculator
								.getBean().calculatePricePerformance(
										currentSectorData.getValue(),
										sectorDto._getClosingPrices(),
										Constants.PRICE_PERF_DAYS_PER_MONTH));

						// one 3 month price perforemence
						stockResult.setThreeMonthIndexPerfor(StockCalculator
								.getBean().calculatePricePerformance(
										currentSectorData.getValue(),
										sectorDto._getClosingPrices(),
										Constants.PRICE_PERF_DAYS_THREE_MONTH));

						// one ytd price perforemence
						stockResult.setYtdIndexPerfor(StockCalculator.getBean()
								.calculateSectorYdt(
										sectorDto.getDailySectorData(),
										currentSectorData.getValue()));

					}
					stockResult.setNoOfCompany(noOfCompanies);

					stockResults.add(stockResult);

				}

			}
			returnData.setData(stockResults);

		} catch (Exception e) {
			logger.error(e.getMessage());

			returnData.setNo(Constants.ERROR);
			returnData.setMsg(e.getMessage());
		}

		return returnData;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.sixtynine.stock.service.StockManagerService#searchDividends(int,
	 * java.util.Date, java.util.Date)
	 */
	public ReturnData<List<DividendResult>> searchDividends(int companyId,
			Date fromDate, Date toDate) {

		ReturnData<List<DividendResult>> returnData = new ReturnData<List<DividendResult>>();
		returnData.setNo(Constants.SUCCESS);

		boolean isSearch = (fromDate != null || toDate != null || companyId > 0);

		List<DividendResult> dividendResults = new ArrayList<DividendResult>();
		try {
			List<CompanyDto> companies = companyCache
					.get(Constants.COMPANY_CACHED_DATA);

			List<BaseEntity> dividends = null;
			for (CompanyDto companyDto : companies) {
				dividends = companyDto.getDividendData();
				int i = 0;
				for (BaseEntity baseEntity : dividends) {
					// if it is not a search, just show the latest date
					if (!isSearch && i > 0) {
						break;
					}
					Dividend dividend = (Dividend) baseEntity;

					// paid before the from date
					if (fromDate != null) {
						if (fromDate.after(dividend.getDate())) {
							continue;
						}
					}

					// paid after the todate
					if (toDate != null) {
						if (toDate.before(dividend.getDate())) {
							continue;
						}
					}

					if (companyId > 0) {
						if (companyId != dividend.getCompany().getId()) {
							continue;
						}
					}

					DividendResult dividendResult = new DividendResult();

					dividendResult.setTicker(dividend.getCompany().getCode());
					dividendResult.setCompanyName(dividend.getCompany()
							.getName());
					dividendResult.setDividendPerShare(dividend
							.getDividedPShare());
					dividendResult.setAdjDividendPerShare(dividend
							.getAdjDividedPShare());
					dividendResult.setBonusIssue(dividend.getBonusIssues());
					dividendResult.setRightIssue(dividend.getRightsIssues());
					dividendResult.setStockSplits(dividend.getStockSplits());

					dividendResults.add(dividendResult);

					i++;
				}

				returnData.setData(dividendResults);
			}

		} catch (ExecutionException e) {
			logger.error(e.getMessage());
			returnData.setMsg(e.getMessage());
			returnData.setNo(Constants.ERROR);
		}

		return returnData;
	}
}
